iT邦幫忙

2023 iThome 鐵人賽

DAY 29
1
自我挑戰組

WiFiBoy Python 玩學機介紹系列 第 29

# 29. 建立玩學機 Arduino 開發環境

  • 分享至 

  • xImage
  •  

玩學機的另一種玩法

除了使用MicroPython 來開發應用程式外,其實我們也可以使用 Arduino IDE 來開發應用程式。不過要注意的是,Arduino IDE 主要是使用 C/C++ 語言來開發。接下來我們來教大家如何按照玩學機手冊裡面的資訊,安裝必備軟體,讓我們也可以使用 C/C++ 語言來開發程式。

安裝必備的軟體

  1. Arduino IDE 2.2.1 版
  2. 安裝必備的硬體驅動程式(Arduino 安裝程式會提醒你)
  3. 加入額外的開發板管理員網址,https://dl.espressif.com/dl/package_esp32_index.json
  4. 安裝後,請點選 File / Preferences ,將 Language 從 English 改選成 中文(繁體),點選OK 後,Arduino IDE 會自動重啟,改成中文介面。
  5. 安裝 WiFiBoy 相關函式庫,選擇 Sketch / 含括程式庫 / 加入 .zip 程式庫。選擇 WiFiBoy.zip與 ESP32.zip。

https://ithelp.ithome.com.tw/upload/images/20230930/20105707EmIkNwzIHO.png

Arduino IDE 設定說明

設定開發版管理員

  1. 檔案 / 喜好設定 / 其他開發版管理員網址,加入「https://dl.espressif.com/dl/package_esp32_index.json」,點選確定。
    https://ithelp.ithome.com.tw/upload/images/20230930/20105707YyH57YXrR0.png
  2. 工具 / 開發板 / 開發板管理員,在搜尋處,輸入 Arduino-ESP32,會出現兩個項目,點選esp32 即可。
    https://ithelp.ithome.com.tw/upload/images/20230930/20105707uaPLO7b9pg.png

https://ithelp.ithome.com.tw/upload/images/20230930/20105707tCiHCrUQPi.png

https://ithelp.ithome.com.tw/upload/images/20230930/20105707atcMrEzlr9.png
3. 選擇開發版為「ESP32 Dev Module 」,連接埠選擇「COM17 Serial Port(USB)」(本例使用的玩學機,作業系統辨識到的COM Port 是 17,請按照您電腦的實際情況,選擇正確的 COM Port)。
https://ithelp.ithome.com.tw/upload/images/20230930/20105707suNr5GxY9P.png

範例實作

玩學運算公司開發了一個 VGA 擴充模組,可以讓您使用 Arduino IDE 開發能輸出玩學機畫面到螢幕上的程式。您只要執行「okesp-160x128-galaxian-lcd-sync-vga-v1r2.ino」程式,將其燒錄到玩學機。把VGA線接到螢幕,就會發現小蜜蜂遊戲的畫面已經同步到電腦螢幕上。這樣玩起來就更舒服。

https://ithelp.ithome.com.tw/upload/images/20230930/20105707vqBSaK7nd8.png

您可以試著閱讀程式碼,就會發現這個小蜜蜂遊戲是由 C 語言實作的。這也是 MicroPyhon 版小蜜蜂的基礎(繪圖引擎)。讀者可以試著修改小蜜蜂的原始碼,就能了解如何在 Arduino 環境中開發小遊戲。

我們也期待玩學運算公司能早一點將 VGA 模組的驅動程式移植到 MicroPython 環境,這樣我們就能開發更多能在電腦螢幕上玩的遊戲或是應用程式。讓 WiFiBoy Python 玩學機變成一台能真正用在生活中的應用工具。

https://ithelp.ithome.com.tw/upload/images/20230930/20105707Jryrt2EHPo.png

https://ithelp.ithome.com.tw/upload/images/20230930/20105707eR7BANIkNu.png

遊戲實際運作情況,可以參考下列影片。

https://www.youtube.com/watch?v=Kz_rWXI6N3I

Arduino 版小蜜蜂程式

// WiFiBoy LCD+VGA Examples
//
// cc by-sa 4.0 license
// bitluni & dereklai
//include libraries
#include <ESP32Lib.h>
#include <Ressources/CodePage437_8x8.h>
#include <wifiboy_lib.h>
#include <math.h>
#include "sprites.h"
extern uint8_t *wb_buf8;
VGA6Bit vga;
///////////////////////////////////////
// VGA Pin Configuration
const int redPins[] = {2,19};
const int greenPins[] = {5,18};
const int bluePins[] = {21,22};
const int hsyncPin = 23;
const int vsyncPin = 26;
char colors[]={ 0x03,0x0b,0x07,0x0f,0x0d,0x0e,0x0c,0x24,0x18,0x30,0x32,0x31,0x33,0x13,0x23,0x03};
//////////////////////////////////////
uint8_t m_x[100];
uint16_t m_y[100];
uint8_t m_v[100];
uint16_t m_c[100];
int xx=60, yy, shooting=0, ct=0, dx=1, dir=2, spn[18], hs=0, sc=0, k=0
void blit_str256(char *str, int x, int y)
{
    int cc;
    for(int i=0; i<strlen(str); i++) {
        if (str[i]>=' '&& str[i]<='~') {
          cc=str[i]-' ';
          wb_blitBuf8(8*(cc%16),8*(cc/16),128, x+i*8, y, 8, 8, (uint8_t *)sprites);
        }
    }
}
void blit_num256(uint16_t num, uint16_t x, uint16_t y)
{
    uint16_t  d[5];
    d[0]=num/10000;
    d[1]=(num-d[0]*10000)/1000;
    d[2]=(num-d[0]*10000-d[1]*1000)/100;
    d[3]=(num-d[0]*10000-d[1]*1000-d[2]*100)/10;
    d[4]=num-d[0]*10000-d[1]*1000-d[2]*100-d[3]/10;
    for(int i=0; i<5; i++) {
        wb_blitBuf8(d[i]*8, 8, 128, x+i*8, y, 8, 8, (uint8_t *)sprites);
    }
}
////////////////////////////
// Beep Sounds
void setup_sound()
{
  pinMode(17, OUTPUT); 
  digitalWrite(17,1); // sound on for buzzer
  pinMode(25, OUTPUT); 
}
void beeper(int freq, int time)
{
  for(int i=0;i<time;i++) {
    digitalWrite(25,1);
    for(int j=0;j<freq; j++) delayMicroseconds(10);
    digitalWrite(25,0);
    for(int j=0;j<freq; j++) delayMicroseconds(10);
  }
}
////////////////////////////

void setup()
{
  vga.setFrameBufferCount(2);
  vga.init(vga.MODE200x150, redPins, greenPins, bluePins, hsyncPin, vsyncPin);
  vga.setFont(CodePage437_8x8);
  wb_init(3);
  wb_initBuf8();
  wb_clearBuf8();
  for(int i=0; i<256; i++) 
    wb_setPal8(i, wb_color565(pals[i][0],pals[i][1],pals[i][2]));
  wb_blitBuf8(0, 0, 128, 0, 0, 128, 128, (uint8_t *)sprites);
  wb_blit8();
  for(int i=0; i<100; i++) {
    m_x[i]=random(0,240);
    m_y[i]=random(0,320);
    m_v[i]=random(2,5);
    m_c[i]=wb_rand(10)+54;
  }
  for(int i=0; i<18; i++) spn[i]=1;
  setup_sound();
}

unsigned char c2c[64]={
  0, 32, 16, 48, 2, 34, 18, 50, 1, 33, 17, 49, 3, 35, 19, 51, 
  8, 40, 24, 56, 10, 42, 26, 58, 9, 41, 25, 57, 11, 43, 27, 59, 
  4, 36, 20, 52, 6, 38, 22, 54, 5, 37, 21, 53, 7, 39, 23, 55, 12, 
  44, 28, 60, 14, 46, 30, 62, 13, 45, 29, 61, 15, 47, 31, 63
};
  
void loop()
{
    int i, j, sx, sy;
    wb_clearBuf8();
    for(i=0; i<100; i++) {
        wb_setBuf8(m_x[i]+m_y[i]*240, m_c[i]);
        m_y[i] += m_v[i];
        if (m_y[i]>=320) m_y[i]-=320;
    }
    if (((wb_getkey()&4)==4) && (xx<143)) xx += 2;
    if (((wb_getkey()&8)==8) && (xx>2)) xx -= 2;
    // fighter
    wb_blitBuf8(24, 48, 128, xx, 112, 16, 16, (uint8_t *)sprites);
    if (((wb_getkey()&1)==1) && (shooting==0)) { 
        yy=110; shooting=1; 
        beeper(400,5);
        //beeper(20,50); beeper(12,50);  
        //beeper(500,5); 
    } 
    if ((wb_getkey()&2)==2) { for(i=0; i<18; i++) spn[i]=1; sc=0; k=0; } 
    // bullet
    if (shooting==1) {
        yy-=5; if (yy<0) { yy=112; shooting=0;}
        wb_blitBuf8(4, 51, 128, xx+5, yy, 3, 4, (uint8_t *)sprites);
    } else wb_blitBuf8(4, 51, 128, xx+5, 112, 3,4,(uint8_t *)sprites); 
    // aliens
    ct += 1;
    if ((ct%4)==0) { 
        dx += dir; 
        if (dx>64) { dir=-2; dx=64; }
        if (dx<1) { dir=2; dx=1; }
    }
    for(i=32; i<97; i+=48) 
        wb_blitBuf8(0, 80, 128, dx+i-16, 12, 16,16, (uint8_t *)sprites);

    for(i=0; i<18; i++) {
        sx = dx+(i%6)*16; 
        sy = (i/6)*16+30;
        if (spn[i]==1) {
            if ((ct+i)%40<20) wb_blitBuf8(0, 64, 128, sx, sy, 16,16, (uint8_t *)sprites);
            else wb_blitBuf8(16, 64, 128, sx, sy, 16,16, (uint8_t *)sprites);
            if ((yy-sy>0) && (yy-sy<16) && (xx+5-sx>0) && (xx+5-sx<13)) {
                spn[i]=20; yy = 0; sc+=100;
                //beeper(10,100); beeper(5,50); beeper(2,50); beeper(1,50);   
                //beeper(400,15); 
                beeper(20,50); beeper(12,50); 
                // beep(900); delay(10); beep(600); delay(10); beep(800); delay(10); beepoff();
            }
        } else if (spn[i]>9) {
          wb_blitBuf8(48, 51, 128, sx+3, sy+3, 8,8, (uint8_t *)sprites);
          spn[i]-=1;
        } else if (spn[i]>3) { 
          wb_blitBuf8(56, 48, 128, sx, sy, 16,16, (uint8_t *)sprites);
          spn[i]-=1;
        } else if (spn[i]==3) {
          spn[i]=2;
          if (++k==18) { k=0; for(j=0; j<18; j++) spn[j]=1; }
        }
    }
    blit_str256("WiFiBoy LCD+VGA", 20, 90);
    blit_str256("H:", 92,0);
    blit_str256("S:", 12,0);
    blit_num256(sc, 28, 0);
    if (sc>hs) hs=sc; 
    blit_num256(hs, 108, 0);
    for(int i=0; i<128; i++) {
      for(int j=0; j<160; j++) {
        vga.dotFast(j+20, i+11, c2c[wb_buf8[i*160+j]]);
      }
    }
    vga.show();
    wb_blit8();
    delay(5);
}

上一篇
28. 玩學機與 Jupyter Notebook 協作
下一篇
30. 進階主題-Forth模擬器
系列文
WiFiBoy Python 玩學機介紹30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言